﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace UDP_Library
{
    public class OmegaUDP
    {
        #region 公共属性

        public bool IsListening { get; set; } = false;

        public string Local_IP { get; set; } = "127.0.0.1";
        public int Local_Port { get; set; } = 9788;


        public string Remote_IP { get; set; }
        public int Remote_Port { get; set; } = 9999;

        #endregion

        #region 委托 事件回传
        /// <summary>
        /// 日志+数据回传
        /// </summary>
        /// <param name="type">[Log][New Data][Send Data][Error]</param>
        /// <param name="log"></param>
        /// <param name="data"></param>
        public delegate void LogFrom_OmegaUDP(string type, string log, byte[] data);//数据回传
        /// <summary>
        /// 数据回传
        /// </summary>
        public event LogFrom_OmegaUDP Got_Log;
        #endregion

        private UdpClient listener = null;

        public OmegaUDP()
        { }


        #region 监听 启停
        /// <summary>
        /// 设置本地IP和端口
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public void Set_Local(string ip, int port)
        {
            Local_IP = ip;
            Local_Port = port;
        }
        /// <summary>
        /// 开启本地监听模式
        /// </summary>
        public void Start_Listener_Local()
        {
            if (listener == null)
            {
                listener = new UdpClient(Local_Port);
            }

            
            IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, Local_Port);
            


            MakeLog("Log", "Start Listening……", null);
            IsListening = true;

            Task.Run(() => {
                try
                {
                    while (IsListening)
                    {
                        byte[] bytes = listener.Receive(ref groupEP); //监听中……，等待数据到来。 2021年12月1日15:43:03
                        if (IsListening)
                        {
                            Got_Log?.Invoke("New Data", "New Data Arrive", bytes);
                        }
                        
                    }
                    
                    MakeLog("Log", "Real End Listen", null);

                }
                catch (Exception ex)
                {
                    MakeLog("Error", ex.Message, null);
                }
                finally
                {
                    ClearUdpClient();
                }
            });

        }

        public void Stop_Listener_Local()
        {
            IsListening = false;
            ClearUdpClient();
            MakeLog("Log", "End Listen", null);
            
        }
        /// <summary>
        /// 关闭udpClient服务端
        /// </summary>
        private void ClearUdpClient()
        {
            if (listener != null)
            {
                listener.Close();
                listener = null;
                MakeLog("Log", "Listener Close", null);
            }
        }
        #endregion


        /// <summary>
        /// 统一调用委托项，制作日志，发送到外围。
        /// </summary>
        /// <param name="type"></param>
        /// <param name="log"></param>
        /// <param name="data"></param>
        private void MakeLog(string type, string log, byte[] data)
        {
            Got_Log?.Invoke(type, log, data);
        }

        private void Set_Remote(string ip, int port)
        {
            Remote_IP = ip;
            Remote_Port = port;
        }

        public void SendData_To_Remote(string ip, int port,byte[] data)
        {
            Set_Remote(ip, port);
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPAddress broadcast = IPAddress.Parse(ip);
            IPEndPoint ep = new IPEndPoint(broadcast, port);
            try
            {
                s.SendTo(data, ep);
                MakeLog("Send Data", "Data Send……", data);
            }
            catch (Exception ex)
            {
                MakeLog("Error", $"{ex.Message} ==> Data Length:{data.Length}", null);
            }
        }
    }
}
